package com.chenchen.tiguan.venue.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.chenchen.tiguan.common.utils.DateUtils;
import com.chenchen.tiguan.common.utils.SecurityUtils;
import com.chenchen.tiguan.venue.domain.Venue;
import com.chenchen.tiguan.venue.domain.VenueCourt;
import com.chenchen.tiguan.venue.domain.VenueTimeSlot;
import com.chenchen.tiguan.venue.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.chenchen.tiguan.venue.domain.VenueClosingSlot;
import com.chenchen.tiguan.venue.service.IVenueClosingSlotService;

/**
 * 场馆闭馆规则Service业务层处理
 * 
 * @author chenchen
 * @date 2025-04-14
 */
@Service
public class VenueClosingSlotServiceImpl implements IVenueClosingSlotService 
{
    @Autowired
    private VenueClosingSlotMapper venueClosingSlotMapper;
    @Autowired
    private VenueMapper venueMapper;
    @Autowired
    private VenueCourtMapper venueCourtMapper;

    @Autowired
    VenueTimeSlotMapper venueTimeSlotMapper;
    @Autowired
    private VenueOpenTimeMapper venueOpenTimeMapper;

    /**
     * 查询场馆闭馆规则
     * 
     * @param closingId 场馆闭馆规则主键
     * @return 场馆闭馆规则
     */
    @Override
    public VenueClosingSlot selectVenueClosingSlotByClosingId(Long closingId)
    {
        return venueClosingSlotMapper.selectVenueClosingSlotByClosingId(closingId);
    }

    /**
     * 查询场馆闭馆规则列表
     * 
     * @param venueClosingSlot 场馆闭馆规则
     * @return 场馆闭馆规则
     */
    @Override
    public List<VenueClosingSlot> selectVenueClosingSlotList(VenueClosingSlot venueClosingSlot)
    {
        return venueClosingSlotMapper.selectVenueClosingSlotList(venueClosingSlot);
    }

    @Override
    public List<VenueClosingSlot> selectVenueClosingSlotByVenueId(Long venueId)
    {
        return venueClosingSlotMapper.selectVenueClosingSlotByVenueId(venueId);
    }

    /**
     * 新增场馆闭馆规则
     * 
     * @param venueClosingSlot 场馆闭馆规则
     * @return 结果
     */
    @Override
    public int insertVenueClosingSlot(VenueClosingSlot venueClosingSlot)
    {
        venueClosingSlot.setCreateTime(DateUtils.getNowDate());
        venueClosingSlot.setCreateBy(SecurityUtils.getUsername());
        return venueClosingSlotMapper.insertVenueClosingSlot(venueClosingSlot);
    }

    /**
     * 修改场馆闭馆规则
     * 
     * @param venueClosingSlot 场馆闭馆规则
     * @return 结果
     */
    @Override
    public int updateVenueClosingSlot(VenueClosingSlot venueClosingSlot)
    {
        venueClosingSlot.setUpdateTime(DateUtils.getNowDate());
        venueClosingSlot.setUpdateBy(SecurityUtils.getUsername());
        return venueClosingSlotMapper.updateVenueClosingSlot(venueClosingSlot);
    }

    /**
     * 批量删除场馆闭馆规则
     * 
     * @param closingIds 需要删除的场馆闭馆规则主键
     * @return 结果
     */
    @Override
    public int deleteVenueClosingSlotByClosingIds(Long[] closingIds)
    {
        return venueClosingSlotMapper.deleteVenueClosingSlotByClosingIds(closingIds);
    }

    /**
     * 删除场馆闭馆规则信息
     * 
     * @param closingId 场馆闭馆规则主键
     * @return 结果
     */
    @Override
    public int deleteVenueClosingSlotByClosingId(Long closingId)
    {
        return venueClosingSlotMapper.deleteVenueClosingSlotByClosingId(closingId);
    }

    @Override
    public int updateTimeSlotStatusWhenInsertAndUpdate(VenueClosingSlot venueClosingSlot) {
        Venue venue = venueMapper.selectVenueByVenueId(venueClosingSlot.getVenueId());
        if(venue!=null){
            List<VenueCourt> venueCourtList = venueCourtMapper.selectVenueCourtListByVenueId(venue.getVenueId());
            if(venueCourtList!=null){
                for (VenueCourt venueCourt : venueCourtList) {
                    List<VenueTimeSlot> venueTimeSlots = venueTimeSlotMapper.selectVenueTimeByCourId(venueCourt.getCourtId());
                    for (VenueTimeSlot venueTimeSlot : venueTimeSlots)
                    {
                        System.out.println(venueTimeSlot.getDate());
                        venueTimeSlot.setStatus(4L);
                        System.out.println("设置成功");
                        int i = venueTimeSlotMapper.updateVenueTimeSlot(venueTimeSlot);
                    }
                    List<VenueTimeSlot> filterTimeSlotList = updateTimeSlotStatusByCase(venueTimeSlots, venueClosingSlot);
                    for (VenueTimeSlot venueTimeSlot : filterTimeSlotList){
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTime(venueTimeSlot.getDate());
                        System.out.println(venueTimeSlot);
                        System.out.println(venueTimeSlot.getDate());
                        venueTimeSlot.setStatus(3L);
                        System.out.println("设置成功");
                        int i = venueTimeSlotMapper.updateVenueTimeSlot(venueTimeSlot);
                    }
                }
            }
        }
        return 0;
    }

    @Override
    public int updateTimeSlotStatusWhenDelete(VenueClosingSlot venueClosingSlot) {
        Venue venue = venueMapper.selectVenueByVenueId(venueClosingSlot.getVenueId());
        if(venue!=null){
            List<VenueCourt> venueCourtList = venueCourtMapper.selectVenueCourtListByVenueId(venue.getVenueId());
            if(venueCourtList!=null){
                for (VenueCourt venueCourt : venueCourtList) {
                    List<VenueTimeSlot> venueTimeSlots = venueTimeSlotMapper.selectVenueTimeByCourId(venueCourt.getCourtId());
                    List<VenueTimeSlot> filterTimeSlotList = updateTimeSlotStatusByCase(venueTimeSlots, venueClosingSlot);
                    for (VenueTimeSlot venueTimeSlot : filterTimeSlotList){
                        System.out.println(venueTimeSlot.getDate());
                        VenueTimeSlot vTarget = new VenueTimeSlot();
                        vTarget.setStatus(4L);
                        venueTimeSlotMapper.updateVenueTimeSlot(vTarget);
                    }
                }
            }
        }
        return 0;
    }

    public List<VenueTimeSlot> updateTimeSlotStatusByCase(List<VenueTimeSlot> venueTimeSlots, VenueClosingSlot venueClosingSlot) {
        List<VenueTimeSlot> finalSlots = new ArrayList<>(venueTimeSlots);

            switch (venueClosingSlot.getType().intValue()) {
                case 1:
                    finalSlots = filterWeeklyClosing(venueTimeSlots, venueClosingSlot);
                    return finalSlots;
                case 2:
                    finalSlots = filterFullDayClosing(venueTimeSlots, venueClosingSlot);
                    return finalSlots;
                case 3:
                    finalSlots = filterTimeRangeClosing(venueTimeSlots, venueClosingSlot);
                    return finalSlots;
                default:
                    throw new IllegalArgumentException("无效的闭馆类型: " + venueClosingSlot.getType());
            }
    }


    /**
     * 过滤每周固定闭馆的时间段
     * @param slots 原始时间段集合
     * @param closing 闭馆规则（type=1时使用）
     * @return 符合闭馆规则的时间段集合
     */
    private List<VenueTimeSlot> filterWeeklyClosing(List<VenueTimeSlot> slots, VenueClosingSlot closing) {
        List<VenueTimeSlot> closingSlots = new ArrayList<>();

        for (VenueTimeSlot slot : slots) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(slot.getDate());

            // 关键逻辑：将Calendar的DAY_OF_WEEK(1=周日,2=周一...7=周六)
            // 转换为0=周日,1=周一...6=周六的格式
            Long slotDayOfWeek = (long) ((cal.get(Calendar.DAY_OF_WEEK) - 1) % 7);

            if (slotDayOfWeek == closing.getDayOfWeek()) {
                // 合并日期和时间部分
                Date slotStart = combineDateTime(slot.getDate(), slot.getStartTime());
                Date slotEnd = combineDateTime(slot.getDate(), slot.getEndTime());

                // 创建闭馆时间段（处理跨天情况）
                Date closingStart = createClosingDateTime(slot.getDate(), closing.getStartTime());
                Date closingEnd = createClosingDateTime(slot.getDate(), closing.getEndTime());

                closingSlots.add(slot);
            }
        }
        return closingSlots;
    }

    private List<VenueTimeSlot> filterFullDayClosing(List<VenueTimeSlot> slots, VenueClosingSlot closing) {
        List<VenueTimeSlot> closingSlots = new ArrayList<>();

        for (VenueTimeSlot slot : slots) {
            boolean sameDay = isSameDay(slot.getDate(), closing.getClosingDate());
            boolean fullDaySlot = isFullDaySlot(slot);

            // 判断日期匹配且为全天时段
            if (sameDay) {
                closingSlots.add(slot);
            }
        }
        return closingSlots;
    }


    private List<VenueTimeSlot> filterTimeRangeClosing(List<VenueTimeSlot> slots, VenueClosingSlot closing) {
        List<VenueTimeSlot> closingSlots = new ArrayList<>();

        Date closingDate = closing.getClosingDate();

        for (VenueTimeSlot slot : slots) {
            // 1. 检查日期是否匹配
            if (!isSameDay(slot.getDate(), closingDate)) {
                continue;
            }

            // 2. 合并时间段的时间部分
            Date slotStart = combineDateTime(slot.getDate(), slot.getStartTime());
            Date slotEnd = combineDateTime(slot.getDate(), slot.getEndTime());

            // 3. 创建闭馆时间范围（处理跨天）
            Date closingStart = createClosingDateTime(closingDate, closing.getStartTime());
            Date closingEnd = createClosingDateTime(closingDate, closing.getEndTime());

            // 4. 检查时间重叠
            if (hasOverlap(slotStart, slotEnd, closingStart, closingEnd)) {
                closingSlots.add(slot);
            }
        }
        return closingSlots;
    }

    // 时间重叠判断（与filterWeeklyClosing同级）
    private boolean hasOverlap(Date start1, Date end1, Date start2, Date end2) {
        return (start1.before(end2) && end1.after(start2))
                || (start2.before(end1) && end2.after(start1));
    }

    // 合并日期时间（类层级方法）
    private Date combineDateTime(Date datePart, Date timePart) {
        Calendar dateCal = Calendar.getInstance();
        dateCal.setTime(datePart);

        Calendar timeCal = Calendar.getInstance();
        timeCal.setTime(timePart);

        dateCal.set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY));
        dateCal.set(Calendar.MINUTE, timeCal.get(Calendar.MINUTE));
        dateCal.set(Calendar.SECOND, timeCal.get(Calendar.SECOND));
        dateCal.set(Calendar.MILLISECOND, 0);

        return dateCal.getTime();
    }

    // 创建闭馆时间段（处理跨天逻辑）
    private Date createClosingDateTime(Date baseDate, Date timePart) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(baseDate);

        Calendar timeCal = Calendar.getInstance();
        timeCal.setTime(timePart);

        // 设置时间部分
        cal.set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY));
        cal.set(Calendar.MINUTE, timeCal.get(Calendar.MINUTE));
        cal.set(Calendar.SECOND, timeCal.get(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, 0);

        // 处理跨天（如23:30-00:30）
        if (timeCal.get(Calendar.DAY_OF_YEAR) != cal.get(Calendar.DAY_OF_YEAR)) {
            cal.add(Calendar.DAY_OF_MONTH, 1);
        }
        return cal.getTime();
    }

    private boolean isFullDaySlot(VenueTimeSlot slot) {
        Calendar start = Calendar.getInstance();
        start.setTime(slot.getStartTime());

        Calendar end = Calendar.getInstance();
        end.setTime(slot.getEndTime());

        // 判断开始时间是否为00:00:00
        boolean startsAtMidnight = start.get(Calendar.HOUR_OF_DAY) == 0
                && start.get(Calendar.MINUTE) == 0
                && start.get(Calendar.SECOND) == 0;

        // 结束时间允许两种格式：
        // 1. 次日00:00:00（跨天）
        // 2. 当日23:59:59
        boolean validEnd = (end.get(Calendar.HOUR_OF_DAY) == 0      // 00:00:00
                && end.get(Calendar.MINUTE) == 0
                && end.get(Calendar.SECOND) == 0)
                || (end.get(Calendar.HOUR_OF_DAY) == 23    // 23:59:59
                && end.get(Calendar.MINUTE) == 59
                && end.get(Calendar.SECOND) == 59);

        return startsAtMidnight && validEnd;
    }
    private boolean isSameDay(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)
                && cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR);
    }
}
